/*
 * @Author: Lin Hongwei
 * @Date: 2022-10-07 21:18:57
 * @LastEditTime: 2022-11-05 10:15:19
 * @LastEditors: Lin Hongwei
 * @email: 1365755396@qq.com
 * @CSDN: https://blog.csdn.net/weixin_45429409
 * @Description: 看板界面
 */
import styled from "@emotion/styled";
import { Spin } from "antd";
import { useCallback } from "react";
import { DragDropContext, DropResult } from "react-beautiful-dnd";
import { useQueryKanban, useSortKanban } from "../../../api/kanban";
import { useQueryTask, useSortTask } from "../../../api/task";
import {
  Drag,
  DragChild,
  Drop,
  DropChild,
} from "../../../components/drag-and-drop";
import { ViewContainer } from "../../../components/lib";
import { useDocumentTitle } from "../../../hooks";
import { Kanban } from "../../../types/kanban";
import { Task } from "../../../types/task";
import { CreateKanBanView } from "./create-kanban";
import { KanBanColumn } from "./kanban-column";
import { TaskModal } from "./task-modal";
import { TaskSearchPanel } from "./task-search-panel";
import {
  useKanbanQueryKey,
  useKanbanSearchParams,
  useProjectInUrl,
  useTaskQueryKey,
  useTaskSearchParams,
} from "./utils";

export const KanBanView = () => {
  useDocumentTitle("看板列表");
  const { data: project } = useProjectInUrl();
  const { data: kanbans, isLoading: kanbanIsLoading } = useQueryKanban(
    useKanbanQueryKey(),
    useKanbanSearchParams()
  );
  const { data: allTasks, isLoading: taskLoading } = useQueryTask(
    useTaskQueryKey(),
    useTaskSearchParams()
  ); //利用reactquery2秒内请求多次只请求一次
  let isLoading = kanbanIsLoading || taskLoading;

  const onDragEnd = useDragEnd(kanbans || [], allTasks || []);
  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <ViewContainer>
        <h1>{project?.name}看板</h1>
        <TaskSearchPanel />
        <ColumnsContailner>
          {isLoading ? (
            <Spin size="large" style={{ margin: "auto" }} />
          ) : (
            <Drop type="COLUMN" direction="horizontal" droppableId="kanban">
              <DropChild style={{ display: "flex" }}>
                {kanbans?.map((item, index) => (
                  <Drag
                    key={`kanban-${item.id}`}
                    draggableId={`kanban-${item.id}`}
                    index={index}
                  >
                    <DragChild>
                      <KanBanColumn kanban={item} />
                    </DragChild>
                  </Drag>
                ))}
              </DropChild>
            </Drop>
          )}
          <CreateKanBanView />
        </ColumnsContailner>
        <TaskModal />
      </ViewContainer>
    </DragDropContext>
  );
};

/**
 * @description: 拖拽回调
 * 一、同看板
 * 1. 高向低，排在to之前
 * 2. 低向高，排在to之后
 *
 * 二、跨看板
 * 1. 插在中间，排在to之前
 * 2. 插在看板末尾（刚好总数组末尾）,toIndex为该看板的总数+1，导致超出
 * 3. 插在看板末尾（非总数组末尾），from不是在总数组中的下一个元素，toIndex为该看板的总数+1，导致to已经不是该看板中的元素了
 * 4. 插在看板末尾（非总数组末尾），刚好from为在总数组中的下一个元素，toIndex为该看板的总数+1，此时to=from，导致to已经不是该看板中的元素了
 */
const useDragEnd = (kanbans: Kanban[], allTasks: Task[]) => {
  const { mutate: sortKanban } = useSortKanban(useKanbanQueryKey());
  const { mutate: sortTask } = useSortTask(useTaskQueryKey());
  return useCallback(
    ({ source, destination, type }: DropResult) => {
      console.log(source, destination, kanbans, allTasks);
      if (!destination) return;
      let data = type == "COLUMN" ? kanbans : allTasks;
      let fromIndex = source.index;
      let toIndex = destination.index;
      let fromId = data?.[fromIndex].id;
      let toId = data?.[toIndex]?.id || 0; //当跨看板移动到的是最后一个（且是数组的最后一个）的时候设置为0
      // if (!fromId || !toId || fromId === toId) return;
      //移动位置不变不触发（排除，排除跨看板，移动到看板末尾(下一个刚好是移动的)，导致index相同）
      if (fromId === toId && source.droppableId == destination.droppableId)
        return;
      let params = { fromId, toId, fromIndex, toIndex };
      if (type == "COLUMN") return sortKanban(params);
      if (type == "ROW") {
        let cross_Params = { ...params, sortType: 0, kanbanId: 0 };
        // let sortType = 0;//0为在当前看板移动，1为跨看板移动
        if (source.droppableId != destination.droppableId) {
          //跨看板移动
          cross_Params.sortType = 1;
          // let fromKanbanId = (data?.[fromIndex] as Task).kanbanId;
          ////当跨看板移动到的是最后一个（且是数组的最后一个）的时候设置为0
          let toKanbanId = (data?.[toIndex] as Task)?.kanbanId || 0;
          let kanbanId = +destination.droppableId; //实际移动到的看板id
          cross_Params.kanbanId = kanbanId; //始终赋值to真实的看板id，供乐观更新
          //当为该看板最后一个（非总数组最后一个）时候to看板id非实际移动到的看板id
          //当为总数组的最有一个时候kanbanid=0
          if (toKanbanId != kanbanId || !toKanbanId) {
            cross_Params.toId = 0;
            // cross_Params.kanbanId = kanbanId;
          }
        }
        sortTask(cross_Params);
      }
    },
    [kanbans, allTasks]
  );
};

const ColumnsContailner = styled.div`
  flex: 1;
  display: flex;
  overflow: hidden;
  margin-right: 2rem;
  overflow-x: scroll;
  padding-bottom: 1rem;
`;
